#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:set sts=4:tabstop=4:expandtab:shiftwidth=4:
# EasyUbuntu - Install commonly requested apps on your (k/X)ubuntu box 
# Copyright (C) 2006 EasyUbuntu team
# https://launchpad.net/products/easyubuntu
# http://easyubuntu.freecontrib.org
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
# 
# About this file: 
# Hopefully this will serve as the backend for all EU gui/non gui frontends
# This function assumes a valid package file (in xml)

import shutil
import time
import os
import sys
import detect
import subprocess

def childNodeWithAttrs(pkglist, desktop, *args):
    """
    Returns a list of strings nodelist and a list of nodes containing the requested element type
    If number of 
        args == 0, function is category listing 
        args == 1, function is subcategory listing in the *given* category
        args == 3, function is package listing in a *given* category and subcategory
        args[0] is category
        args[1] is subcategory
        args[2] is type, pkg or config or preconfig or label
    """
    arch = detect.architecture()
    # FIXME: methodology needs to be decided
    if len(args) == 3:
        subcatlist, subcatnodelist = childNodeWithAttrs(pkglist, desktop,  args[0])
        try:
            subcatindex = subcatlist.index(args[1])
            for subcatname in subcatlist:
                if subcatname == args[1]:
                    pkgnodelist = subcatnodelist[subcatindex].getElementsByTagName(args[2])
                    pkgtxtlist = []
                    for pkgname in pkgnodelist:
                        pkgtxtlist.append(pkgname.firstChild.data.encode())
                    return pkgtxtlist, pkgnodelist
        except ValueError:
            return 
    
    elif len(args) == 1:
        catlist, catnodelist = childNodeWithAttrs(pkglist,desktop)
        try:
            catindex = catlist.index(args[0])
            for catname in catlist: 
                if catname == args[0]:
                    subcatnodelist = catnodelist[catindex].getElementsByTagName('subcat')
                    subcatlist = []
                    for subcatname in subcatnodelist:
                        archs = subcatname.attributes["arch"].value.encode()
                        des = subcatname.attributes["de"].value.encode()
                        # List of supported archs by the subcategory
                        if arch in archs.split("-") and ( desktop == \
                                'gnome-kde' or desktop in des.split("-")):
                                subcatlist.append(subcatname.attributes["id"].value)
                        else:
                            subcatlist.append("N/A")
                    #print catname, subcatlist
                    return subcatlist, subcatnodelist
        
        except ValueError:
            sys.stderr.write("Not found any subcategories")
            return

    elif len(args) == 0:
        catnodelist = pkglist.getElementsByTagName('category') #category list in xml
        catlist = []
        for catname in catnodelist:
            catlist.append(catname.attributes["id"].value)
        return catlist, catnodelist 
    
    else:
       sys.stderr.write("Error")

class Utils:

    def __init__(self):
        """ To create the time string for backup
            Format = filename-eu-yyyy-mm-dd-hh-mm-ss
        """
        self.t = "-eu"
        for part in time.localtime()[0:6]:
            self.t += "-" + str(part)
    
    def cp(self, In = None, Out = None):
        """ Copy a file and make a time based backup of the previous
        """
        shutil.move(Out, Out + self.t)
        shutil.copy(In, os.path.split(Out)[0])
    
    def bck(self, File = None):
        if os.path.isfile(File):
            shutil.copy(File, File + self.t)
        # if it is a directory, copy the entire tree
        elif os.path.isdir(File):
            shutil.copytree(File, File + self.t)

def processPreconfig(preconfiglist):
    """
    Given a list of commands of the type 'dmesg | grep hda | grep foo' 
    Executes each one of them and returns the output
    """
    output = []
    for preconfig in preconfiglist:
        cmds = preconfig.split("|")

        for idx, cmd in enumerate(cmds):
            cmd = cmd.strip()
            if idx == 0:
                p = subprocess.Popen(cmd.split(" "), stdout=subprocess.PIPE)
            else:
                p = subprocess.Popen(cmd.split(" "), stdin=p.stdout, stdout=subprocess.PIPE)
        output.append(p.communicate()[0])
    return output

def processConfig(configlist,confdir):
    """
    Provides methods for performing installation and 
    configuration
    """
    commandslist = []
    # Format the selected packages for installation

    if configlist:
        for configcmd in configlist:
            commandslist.append(formatConfig(configcmd, confdir))
    return commandslist

def processInstall(packagelist,confdir):
    """
    Returns list of commands to perform installation of packages
    """
    commandslist = []
    # Format the selected packages for installation
    base_cmd = "apt-get "
    option1 = " -o=dir::etc=" + confdir
    option2 = " -o=dir::etc::sourcelist=sources.list"
    apt_cmd = base_cmd + option1 + option2 
    if packagelist:
        commandslist.append(apt_cmd + " update")
        apt_get_packages = apt_cmd + " --yes --allow-unauthenticated  install"
        for eachpackage in packagelist:
            apt_get_packages = apt_get_packages + " " + eachpackage
        commandslist.append(apt_get_packages)

    return commandslist

def formatConfig(configcmd, confdir):
    """
    Purpose of this function is:
    1) Convert paths in arguments to absolute paths
    2) If we are overwriting a existing file, create a time based backup of
    that file
    FIXME: parse &gt; &lt; xml entities
    """
    arguments = configcmd.encode().split(" ")
    if arguments[0] == "mv" or arguments[0] == "cp":
        # If we are overwriting a file, back it up
        if os.path.exists(arguments[2]):
            cmd=Utils()
            cmd.bck(arguments[2]) #yay for garbage collection
    # If contains $confdir, replace by confdir
    if len(arguments) > 1 and "$confdir" in arguments[1].split("/"):
        configcmd = arguments[0] + " " + arguments[1].replace("$confdir",confdir) + " " + arguments[2]
        return configcmd
    else:
        # if not of the above type , "dpkg-reconfigure xserver-xorg"
        # type of commands
        return configcmd


if __name__ == "__main__":
    from xml.dom import minidom
    from detect import codename, de
    pkglist = minidom.parse('packagelist-%s.xml' % codename())
    desktop = de()

    print "Testing Category listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop)
    print txtlist
    print "Testing Subcategory listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop,'system')
    print txtlist
    print "Testing Package listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop, "multimedia", "freecodecs", "pkg")
    print txtlist
    print "Testing Preconfig listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop, "web", "flash", "preconfig")
    print txtlist
    
    print "Testing config listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop, "system", "sourceslist", "config")
    print txtlist
    print "Testing label listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop, "multimedia", "freecodecs", "label")
    print txtlist
    print "Testing alert listing"
    txtlist, nodelist = childNodeWithAttrs(pkglist, desktop, "multimedia", "freecodecs", "alert")
    print txtlist
